﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace MyCameraLinkCommunication
{

    class clSerialException : System.Exception
    {
        public clSerialException(String error) : base(error) { }
    }

   public class MyClAllSerial
   {

       #region Native Methods   MVTec\HALCON-12.0\genicam\bin\Win64_x64\CLAllSerial_MD_VC80_v2_3.dll  2019-06-21 ludc 
       class NativeMethods
       {
           private NativeMethods() { }

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clFlushPort(IntPtr serialRef);

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clGetErrorText(Int32 errorCode, IntPtr errortext, out UInt32 errorTextSize);


           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clGetNumBytesAvail(IntPtr serialRef, out UInt32 numBytes);


           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clGetNumPorts(out UInt32 numPorts);

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]           
           internal static extern Int32 clGetPortInfo(UInt32 serialIndex, IntPtr manufactureName, out UInt32 nameBytesSize, IntPtr portID, out UInt32 idBytesSize, out UInt32 version);
          

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clGetSupportedBaudRates(IntPtr serialRef, out UInt32 baudRates);



           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clSerialClose(IntPtr serialRef);

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clSerialInit(UInt32 serialIndex, out IntPtr serialRef);

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clSerialRead(IntPtr serialRef, IntPtr buffer, out UInt32 numBytes, UInt32 serialTimeout);

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clSerialWrite(IntPtr serialRef, String buffer, out UInt32 numBytes, UInt32 serialTimeout);

           [DllImport("CLAllSerial_MD_VC80_v2_3.dll", CallingConvention = CallingConvention.Cdecl)]
           internal static extern Int32 clSetBaudRate(IntPtr serialRef, UInt32 baudRate);          
          
          
       }
       #endregion



       #region Error handling Methods
       private static void ThrowOnSerialError(Int32 status, String action)
       {
           if (status != 0)
           {
               String error = action;
               throw new clSerialException(error);
           }
       }
       #endregion
      

       //获取端口数量
       public static void GetNumPorts(out UInt32 numPorts)
       {
           ThrowOnSerialError(NativeMethods.clGetNumPorts(out numPorts), "Cannot retrieve number of ports");
       }


       /// <summary>
       /// 
       /// </summary>
       /// <param name="serialIndex"></param>
       /// <param name="ManufacturerName">制造商名称</param>
       /// <param name="PortID">端口标识</param>
       /// <param name="Version">版本</param>
       public static void GetPortInfo(UInt32 serialIndex, ref string ManufacturerName, ref string PortID, ref uint Version)
       {
           

           UInt32 nameBufferSize=0;          
           UInt32 idBufferSize=0;
           UInt32 version;

           //先获取 bufferSize 大小
           try
           {
               NativeMethods.clGetPortInfo(serialIndex, System.IntPtr.Zero, out nameBufferSize, System.IntPtr.Zero, out idBufferSize, out version);
           }
           catch
           {

           }

           //分配内存   
          IntPtr manufacturerNameIntPtr = Marshal.AllocHGlobal((int)nameBufferSize );
          IntPtr portIDIntPtr = Marshal.AllocHGlobal((int)idBufferSize );

           //获取指针
          NativeMethods.clGetPortInfo(serialIndex, manufacturerNameIntPtr, out nameBufferSize, portIDIntPtr, out idBufferSize, out version);
           
           //获取指针中的字符串
          ManufacturerName = Marshal.PtrToStringAnsi(manufacturerNameIntPtr);
          PortID = Marshal.PtrToStringAnsi(portIDIntPtr);

           //释放内存
          Marshal.FreeHGlobal(manufacturerNameIntPtr);
          Marshal.FreeHGlobal(portIDIntPtr);
       }



       public static void SerialClose(IntPtr serialRef)
       {
           ThrowOnSerialError(NativeMethods.clSerialClose(serialRef),
               "Cannot close port");
       }

       public static void SerialInit(UInt32 serialIndex, out IntPtr serialRef)
       {
           ThrowOnSerialError(NativeMethods.clSerialInit(serialIndex, out serialRef),
               String.Format("Cannot initialize port (index = {0})", serialIndex));
       }

       public static void SerialRead(IntPtr serialRef, IntPtr buffer, out UInt32 numBytes, UInt32 serialTimeout)
       {
           ThrowOnSerialError(NativeMethods.clSerialRead(serialRef, buffer, out numBytes, serialTimeout),
               "Cannot read port");
       }

       public static void SerialWrite(IntPtr serialRef, String buffer, out UInt32 numBytes, UInt32 serialTimeout)
       {
           ThrowOnSerialError(NativeMethods.clSerialWrite(serialRef, buffer, out numBytes, serialTimeout),
               "Cannot write port");
       }


       public static void GetNumBytesAvail(IntPtr serialRef, out UInt32 numBytes)
       {
           ThrowOnSerialError(NativeMethods.clGetNumBytesAvail(serialRef, out numBytes),
               "Cannot retrieve number of bytes available");
       }


       public static void SetBaudRate(IntPtr serialRef,  UInt32 numBytes)
       {
           ThrowOnSerialError(NativeMethods.clSetBaudRate(serialRef,  numBytes),
               "Cannot retrieve number of bytes available");
       }


       public static void GetSupportedBaudRates(IntPtr serialRef, out UInt32 baudRates)
       {
           

           ThrowOnSerialError(NativeMethods.clGetSupportedBaudRates(serialRef,out baudRates),
               "Cannot retrieve number of bytes available");
       }


       
    }
}
